package exam3;

import java.util.LinkedList;

public class Memory {
    private PageTable pageTable = new PageTable();
    private LinkedList<Integer> mainMemory = new LinkedList<>(); // 使用LinkedList实现FIFO队列再好不过了
    // 不过由于指导书后面要求是要输出数组p，所以p[]，和k，还是需要有（悲
    private int[] p = new int[4];
    private int k;

    public void initMemory(){
        k=0; // 初始化k
        for (int i = 0; i < 4; i++) {
            this.mainMemory.addLast(i);
            p[i] = i;
        }
    }

    public void initPageTable(){
        pageTable.add(new Page(0,1,5,11));
        pageTable.add(new Page(1,1,8,12));
        pageTable.add(new Page(2,1,9,13));
        pageTable.add(new Page(3,1,1,21));
        pageTable.add(new Page(4,0,-1,22));
        pageTable.add(new Page(5,0,-1,23));
        pageTable.add(new Page(6,0,-1,121));
//        pageTable.add(new Page());
    }

    public Page getPage(int pageNum){
        Page page = pageTable.find(pageNum);
        if (page.getSignal() == 0){

            return null;
        }else{

            return page;
        }

//        return null;
    }

    public void doFIFOReplace(int newPageNum){
        // 维护FIFO队列
        int outPageNum = this.mainMemory.removeFirst(); // 队首出队
        if (pageTable.find(outPageNum).getModifySignal() == 1){
            // 如果这个页被修改过了，那就必须要OUT调出再IN调入
            System.out.println("OUT: " + outPageNum);
        }
        this.mainMemory.addLast(newPageNum); // 进入到队尾
        System.out.println("IN: " + newPageNum);

        p[k] = newPageNum;
        k = (k + 1) % 4;

        // 更新页表
        Page page = pageTable.find(outPageNum); // 找到被替换出去的旧页的页表项
        page.setSignal(0); // 已经被替换，设标志为：不在内存中
        page.setMemoryNum(-1); // 表示没有内存块号
        page = pageTable.find(newPageNum); // 找到新页的页表项
        page.setSignal(1); // 新页设标志为：在内存中
        page.setMemoryNum(mainMemory.indexOf(newPageNum)); // 设置新页在内存中的块号
    }

    public void printFIFOQueue() {
        System.out.println("k = " + k);
        System.out.print("p =");
        for (int i : p) {
            System.out.print(" " + i);
        }
        System.out.println();
    }

    public void printPageTable(){
        pageTable.getList().forEach(page -> {
            System.out.println(page);
        });
    }

    public void printMem() {
        System.out.println(mainMemory);
    }
}
